package net.cloudsun.graph.puzzle;

import net.cloudsun.graph.puzzle.relation.LeftRoll;
import net.cloudsun.graph.puzzle.relation.UpRoll;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 状态关系
 * created at 23/11/2021
 *
 * @author 俞建波
 * <a href="mailto://yujianbo@chtwm.com">yujianbo@chtwm.com</a>
 * @since 1.1.0
 */
public class PuzzleStateRelation {
    public static Pair<Integer> getLocation(JigsawState jigsawState, int num) {
        int[][] ints = jigsawState.toArray();
        int row = -1;
        int column = -1;
        for (int i = 0; i < ints.length; i++) {
            for (int j = 0; j < ints[i].length; j++) {
                if (ints[i][j] == num) {
                    row = i;
                    column = j;
                }
            }
        }
        final Pair<Integer> integerPair = new Pair<>();
        integerPair.setA(row);
        integerPair.setB(column);
        return integerPair;
    }


    /**
     *
     * @param origin
     * @param direction
     * @return
     */
    public static JigsawState get(JigsawState origin, PuzzleDirection direction) {
        final int[][] ints = origin.toArray();
        final Pair<Integer> location = getLocation(origin, 8);
        swap(ints, location.getA(), location.getB(), direction);
        return new JigsawState(ints);
    }

    public static void swap(int[][] ints, Pair<Integer> location, PuzzleDirection direction) {
        swap(ints, location.getA(), location.getB(), direction);
    }

    public static void swap(int[][] ints, int row, int column, PuzzleDirection direction) {
        int temp = ints[row][column];
        switch (direction) {
            case UP:
                ints[row][column] =  ints[row - 1][column];
                ints[row - 1][column] = temp;
                break;
            case DOWN:
                ints[row][column] =  ints[row + 1][column];
                ints[row + 1][column] = temp;
                break;
            case LEFT:
                ints[row][column] =  ints[row][column - 1];
                ints[row][column - 1] = temp;
                break;
            case RIGHT:
                ints[row][column] =  ints[row][column + 1];
                ints[row][column + 1] = temp;
                break;
            default:
                break;
        }
    }
    public static Map<PuzzleDirection,JigsawState> brothersByCorner(int[][] ints, int row, int column) {
        /*
         * 四个角只有两个方向
         * 角落四种情况
         * 0 0, 0 2, 2 0, 2 2
         */
        Map<PuzzleDirection,JigsawState> map = new HashMap<>(4);
        if (row == 0) {
            map.put(PuzzleDirection.DOWN,downAndRecover(ints, row, column));
        } else {
            map.put(PuzzleDirection.UP,upAndRecover(ints, row, column));
        }

        if (column == 0) {
            map.put(PuzzleDirection.RIGHT,rightAndRecover(ints, row, column));
        } else {
            map.put(PuzzleDirection.LEFT,leftAndRecover(ints, row, column));
        }

        return map;

    }

    public static Map<PuzzleDirection,JigsawState> brothersByEdgeCenter(int[][] ints, int row, int column) {
        // 0 1, 1 0, 1 2, 2 1
        Map<PuzzleDirection,JigsawState> map = new HashMap<>(4);

        if (row == 0) {
            map.put(PuzzleDirection.DOWN,downAndRecover(ints, row, column));
        } else if (row == 2) {
            map.put(PuzzleDirection.UP,upAndRecover(ints, row, column));
        } else {
            // 上下都行
            map.put(PuzzleDirection.DOWN,downAndRecover(ints, row, column));
            map.put(PuzzleDirection.UP,upAndRecover(ints, row, column));
        }

        if (column == 0) {
            map.put(PuzzleDirection.RIGHT,rightAndRecover(ints, row, column));
        } else if (column == 2) {
            map.put(PuzzleDirection.LEFT,leftAndRecover(ints, row, column));
        } else {
            // 左右都行
            map.put(PuzzleDirection.RIGHT,rightAndRecover(ints, row, column));
            map.put(PuzzleDirection.LEFT,leftAndRecover(ints, row, column));
        }
        return map;
    }


    public static Map<PuzzleDirection,JigsawState> brothersByCenter(int[][] ints, int row, int column) {
        Map<PuzzleDirection,JigsawState> map = new HashMap<>(4);
        // 交换位置,然后new
        map.put(PuzzleDirection.LEFT,leftAndRecover(ints, row, column));
        map.put(PuzzleDirection.RIGHT,rightAndRecover(ints, row, column));
        map.put(PuzzleDirection.UP,upAndRecover(ints, row, column));
        map.put(PuzzleDirection.DOWN,downAndRecover(ints, row, column));
        return map;
    }

    private static JigsawState upAndRecover(int[][] ints, int row, int column) {
        PuzzleStateRelation.swap(ints, row, column, PuzzleDirection.UP);
        final JigsawState jigsawState = new JigsawState(ints);
        PuzzleStateRelation.swap(ints, row - 1, column, PuzzleDirection.DOWN);
        return jigsawState;
    }

    private static JigsawState downAndRecover(int[][] ints, int row, int column) {
        PuzzleStateRelation.swap(ints, row, column, PuzzleDirection.DOWN);
        final JigsawState jigsawState = new JigsawState(ints);
        PuzzleStateRelation.swap(ints, row + 1, column, PuzzleDirection.UP);
        return jigsawState;
    }

    private static JigsawState rightAndRecover(int[][] ints, int row, int column) {
        PuzzleStateRelation.swap(ints, row, column, PuzzleDirection.RIGHT);
        final JigsawState jigsawState = new JigsawState(ints);
        PuzzleStateRelation.swap(ints, row, column + 1, PuzzleDirection.LEFT);
        return jigsawState;
    }

    private static JigsawState leftAndRecover(int[][] ints, int row, int column) {
        PuzzleStateRelation.swap(ints, row, column, PuzzleDirection.LEFT);
        final JigsawState jigsawState = new JigsawState(ints);
        PuzzleStateRelation.swap(ints, row, column - 1, PuzzleDirection.RIGHT);
        return jigsawState;
    }


}
